package web

import (
	"github.com/gin-gonic/gin"
	"go-admin/server/internal/domain"
	"go-admin/server/internal/service"
	"go-admin/server/internal/web/form"
	"go-admin/server/utils"
	"net/http"
)

type RbacHandler struct {
	svc service.RbacService
}

func NewRbacHandler(svc service.RbacService) *RbacHandler {
	return &RbacHandler{
		svc: svc,
	}
}

func (r *RbacHandler) RegisterRoutes(server *gin.Engine) {
	g := server.Group("/rbac")

	g.PUT("/create-role", r.createRole)
	g.PUT("/update-role", r.updateRole)
	g.DELETE("/del", r.delRole)
	g.GET("/role-lst", r.roleLst)

	g.GET("/auth-data", r.authData)
	g.GET("/admin-role-lst", r.adminRoleLst)
	g.PUT("/auth", r.auth)
}

// createRole 创建角色
func (r *RbacHandler) createRole(ctx *gin.Context) {
	var createData form.RoleData
	err := ctx.Bind(&createData)
	if err != nil {
		return
	}
	err = utils.Verify(createData, utils.RoleVerify)
	err = r.svc.CreateRole(ctx.Request.Context(), domain.RoleData{
		RoleName:    createData.RoleName,
		Description: createData.Description,
	})
	switch err {
	case nil:
		RenderJSON(ctx, http.StatusOK, http.StatusOK, "添加成功", nil)
		return
	case service.ErrRoleDuplicate:
		RenderJSON(ctx, http.StatusOK, http.StatusNoContent, "该角色已存在", nil)
		return
	default:
		RenderJSON(ctx, http.StatusOK, http.StatusNoContent, "添加失败", nil)
		return
	}

}

// updateRole 更新角色
func (r *RbacHandler) updateRole(ctx *gin.Context) {
	var updateData form.RoleData
	err := ctx.Bind(&updateData)
	if err != nil {
		return
	}
	err = utils.Verify(updateData, utils.RoleVerify)
	if err != nil {
		RenderJSON(ctx, http.StatusOK, http.StatusNoContent, err.Error(), nil)
		return
	}
	err = utils.Verify(updateData, utils.RoleIDVerify)
	if err != nil {
		RenderJSON(ctx, http.StatusOK, http.StatusNoContent, err.Error(), nil)
		return
	}
	err = r.svc.UpdateRole(ctx.Request.Context(), domain.RoleData{
		RoleID:      updateData.RoleID,
		RoleName:    updateData.RoleName,
		Description: updateData.Description,
	})
	if err != nil {
		RenderJSON(ctx, http.StatusOK, http.StatusNoContent, "更新失败", nil)
		return
	}
	RenderJSON(ctx, http.StatusOK, http.StatusOK, "更新成功", nil)
	return
}

// delRole 删除角色
func (r *RbacHandler) delRole(ctx *gin.Context) {
	var delData form.RoleData
	err := ctx.Bind(&delData)
	if err != nil {
		return
	}
	err = utils.Verify(delData, utils.RoleIDVerify)
	if err != nil {
		RenderJSON(ctx, http.StatusOK, http.StatusNoContent, err.Error(), nil)
		return
	}
	err = r.svc.DelRole(ctx.Request.Context(), delData.RoleID)
	if err != nil {
		RenderJSON(ctx, http.StatusOK, http.StatusNoContent, "删除失败", nil)
		return
	}
	RenderJSON(ctx, http.StatusOK, http.StatusOK, "删除成功", nil)
	return
}

// roleLst 角色列表
func (r *RbacHandler) roleLst(ctx *gin.Context) {
	lst, _ := r.svc.RoleLst(ctx)
	RenderJSON(ctx, http.StatusOK, http.StatusOK, "ok", lst)
}

// authData 授权菜单树
func (r *RbacHandler) authData(ctx *gin.Context) {
	var auth form.AuthRoleID
	err := ctx.BindQuery(&auth)
	if err != nil {
		return
	}
	err = utils.Verify(auth, utils.RoleIDVerify)
	if err != nil {
		RenderJSON(ctx, http.StatusOK, http.StatusNoContent, err.Error(), nil)
		return
	}
	lst, _ := r.svc.AuthDataLst(ctx.Request.Context(), auth.RoleID)
	var tree struct {
		Trees []domain.RoleMenuData `json:"trees"`
	}
	tree.Trees = lst
	RenderJSON(ctx, http.StatusOK, http.StatusOK, "ok", tree)
}

// auth 授权操作
func (r *RbacHandler) auth(ctx *gin.Context) {
	var authData form.AuthData
	err := ctx.Bind(&authData)
	if err != nil {
		return
	}
	//err = utils.Verify(authData.Auth, utils.AuthRoleMap)
	//if err != nil {
	//	RenderJSON(ctx, http.StatusOK, http.StatusNoContent, err.Error(), nil)
	//	return
	//}
	err = utils.Verify(authData, utils.RoleIDVerify)
	if err != nil {
		RenderJSON(ctx, http.StatusOK, http.StatusNoContent, err.Error(), nil)
		return
	}
	err = r.svc.AuthOperation(ctx.Request.Context(), domain.AuthData{
		RoleID: authData.RoleID,
		Auth:   authData.Auth,
	})
	if err != nil {
		RenderJSON(ctx, http.StatusOK, http.StatusNoContent, "操作失败", nil)
		return
	}
	RenderJSON(ctx, http.StatusOK, http.StatusOK, "操作成功", nil)
	return
}

func (r *RbacHandler) adminRoleLst(ctx *gin.Context) {
	data, _ := r.svc.GetAdminRoleData(ctx.Request.Context())
	RenderJSON(ctx, http.StatusOK, http.StatusOK, "ok", data)
}
